<template>
  <view class="pro-form">
    <basic-components />
    <uni-forms ref="formRef" label-position="left" :model="model" :rules="rules" :label-width="labelWidth" @submit.prevent>
      <template v-for="(item, index) of displayOptions">
        <!-- 标题 -->
        <view v-if="verifyItemType(item, formFlag.TITLE)" :key="item.prop" class="title" :class="[index !== 0 ? 'm-t-5' : '']">
          <view class="tag" />
          {{ item.label }}
        </view>

        <uni-forms-item v-else :key="index" :label="item.label" :name="item.prop" :required="isRequired(item)">
          <!-- 页面跳转 -->
          <view v-if="verifyItemType(item, formFlag.SKIP)" class="f-center w100">
            <uni-easyinput
              v-model="model[item.prop]"
              trim
              v-bind="(item.attrs as any)"
              :styles="inputStyle"
              class="right-input"
              :input-border="false"
              :clearable="false"
              :disabled="true"
              :placeholder="setPlaceholder(item, formFlag.SKIP)"
            />
            <uni-icons
              v-if="isDisplayClearIcon(item)"
              type="clear"
              color="#c0c4cc"
              size="24"
              @click="clearValue(item, 'clearMethod')"
            />
            <text class="iconfont icon-dianji ml5" @tap="skipPage(item)" />
          </view>

          <!-- 普通 input 框 -->
          <uni-easyinput
            v-if="verifyItemType(item, formFlag.INPUT)"
            :ref="item.prop"
            v-model="model[item.prop]"
            :focus="modelFocus[item.prop]"
            trim
            v-bind="(item.attrs as any)"
            :styles="inputStyle"
            class="right-input"
            :input-border="false"
            :placeholder="setPlaceholder(item, formFlag.INPUT)"
            @input="changeInput(item, 'inputMethod')"
            @focus="inputFocus(item)"
            @blur="itemMethod(item, 'blurFunction')"
          />

          <!-- 时间选择(自定义) -->
          <view v-if="verifyItemType(item, formFlag.DATE_CUSTOM)" :class="setDateClass(item)">
            <uni-easyinput
              v-model="model[item.prop]"
              trim
              v-bind="(item.attrs as any)"
              :styles="inputStyle"
              class="right-input"
              :input-border="false"
              :clearable="false"
              :disabled="true"
              :placeholder="setPlaceholder(item, formFlag.SKIP)"
            />
            <uni-icons
              v-if="isDisplayClearIcon(item)"
              type="clear"
              color="#c0c4cc"
              size="24"
              @click="clearValue(item, 'clearMethod')"
            />
            <text class="iconfont icon-dianji ml5" @tap="displayDataPicker(item)" />
            <MDatePicker v-model:dValue="model[item.prop]" v-model:visible="item.dateVisible" v-bind="(item.attrs as any)" />
          </view>

          <!--时间选择(uni-app)  -->
          <view v-if="verifyItemType(item, formFlag.DATE)" :class="setDateClass(item)">
            <view class="date" :class="dateValueClass(item)">
              <uni-datetime-picker
                v-model="model[item.prop]"
                v-bind="(item.attrs as any)"
                :placeholder="setPlaceholder(item, formFlag.DATE)"
                hide-second
                :border="false"
              />
            </view>
          </view>

          <!--自定义组件  -->
          <view v-if="verifyItemType(item, formFlag.SLOT)" class="slot">
            <slot :name="item.prop" :model="model[item.prop]"></slot>
          </view>

          <!-- 下拉选择器 -->
          <uni-data-select
            v-if="verifyItemType(item, formFlag.SELECT)"
            v-model="model[item.prop]"
            class="form-data-select"
            v-bind="item.attrs"
            :localdata="(item.children as any)"
            :placeholder="setPlaceholder(item, formFlag.SELECT)"
            :input-border="false"
            @change="value => itemMethod(item, 'changeMethod', value)"
          />

          <!-- 多级联动 -->
          <view v-if="verifyItemType(item, formFlag.DATA_PICKER)" class="data-picker">
            <view class="picker" :class="[model[item.prop] ? 'have-value' : '']">
              <uni-data-picker
                v-model="model[item.prop]"
                :clear-icon="false"
                v-bind="(item.attrs as any)"
                :border="false"
                :localdata="(item.children as any)"
                :placeholder="setPlaceholder(item, formFlag.DATA_PICKER)"
              />
            </view>
          </view>
        </uni-forms-item>
      </template>
    </uni-forms>
  </view>
</template>
<script setup lang="ts" name="">
import { FromOptionsProp } from "./interface/index";
import { useOther } from "./hooks/use-other";
import { useSkip } from "./hooks/use-skip";
import { useInput } from "./hooks/use-input";
import { useDate } from "./hooks/use-date";

export interface ProFormProps {
  labelWidth?: string;
  options: FromOptionsProp[];
}

// 接受父组件参数，配置默认值
const props = withDefaults(defineProps<ProFormProps>(), {
  labelWidth: "120px",
  options: () => []
});

// 表单需要显示的项
const displayOptions = computed(() => props.options.filter(op => !op.hide));

// 验证规则
const rules = computed(() => {
  const r = {};
  for (const item of displayOptions.value) {
    if (item?.rules) {
      r[item["prop"]] = {
        rules: item.rules
      };
    }
  }
  return r;
});

const $emit = defineEmits(["save", "getModel", "submit"]);

const formFlag = FORM_FLAG;
let formRef = ref();
// 表单绑定内容
let model = ref({});

const { inputStyle, verifyItemType, setPlaceholder } = useOther();
const { skipPage } = useSkip(props, model);
const { setDateClass, dateValueClass } = useDate(model);

const { modelFocus, correctionInputValue, inputFocus } = useInput(model);

onBeforeMount(() => {
  init();
});

// 初始化
const init = async () => {
  await initForm();
  $emit("save", handleConfirm);
  $emit("getModel", model.value);
};

// 设置默认值
const initForm = () => {
  const m = {};

  // 获取初始model中内容
  for (const item of props.options) {
    const { defaultValue, prop } = item || {};
    // 设置默认值

    if (prop) m[prop] = defaultValue ?? "";
    // 设置光标默认值
    modelFocus[prop] = false;
  }
  // 避免修改到 defaultValue 的值
  model.value = JSON.parse(JSON.stringify(m));
};

// 是否必填
const isRequired = (item: FromOptionsProp) => {
  return item?.rules?.length && item.rules[0].required;
};

// 点击清楚按钮
const clearValue = (item: FromOptionsProp, methodStr: string) => {
  model.value[item.prop] = "";
  itemMethod(item, methodStr);
};

const changeInput = (item: FromOptionsProp, methodStr: string) => {
  correctionInputValue(item);
  itemMethod(item, methodStr);
};
// 是否隐藏自定义清除图标
const isDisplayClearIcon = (item: FromOptionsProp) => {
  const { clearable, disabled } = item?.attrs || {};
  return model.value[item.prop] && clearable !== false && disabled !== true;
};

// 提交
const handleConfirm = () => {
  formRef.value.validate(err => {
    if (!err) $emit("submit", model.value);
  });
};

// 打开自定义时间组件
const displayDataPicker = (item: FromOptionsProp) => {
  if (item?.attrs?.disabled) return;
  item.dateVisible = true;
};

// 调用属性中绑定的方法
const itemMethod = (item: FromOptionsProp, methodStr: string, value?) => {
  if (typeof item[methodStr] === "function") {
    item[methodStr](model.value, value);
  }
};

defineExpose({
  model
});
</script>
<style lang="scss" src="./index.scss"></style>
